/*     */ package com.zimbra.cs.service.authenticator;
/*     */ 
/*     */ import com.zimbra.common.account.Key.AccountBy;
/*     */ import com.zimbra.common.account.ZAttrProvisioning.AutoProvAuthMech;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException;
/*     */ import com.zimbra.cs.account.Domain;
/*     */ import com.zimbra.cs.account.GuestAccount;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.account.krb5.Krb5Principal;
/*     */ import java.io.IOException;
/*     */ import java.security.Principal;
/*     */ import java.util.Arrays;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ import javax.servlet.http.HttpServletResponse;
/*     */ import org.eclipse.jetty.http.HttpHeader;
/*     */ import org.eclipse.jetty.security.LoginService;
/*     */ import org.eclipse.jetty.security.SpnegoLoginService;
/*     */ import org.eclipse.jetty.security.SpnegoUserIdentity;
/*     */ import org.eclipse.jetty.security.SpnegoUserPrincipal;
/*     */ import org.eclipse.jetty.security.UserAuthentication;
/*     */ import org.eclipse.jetty.server.Authentication;
/*     */ import org.eclipse.jetty.server.Request;
/*     */ import org.eclipse.jetty.server.UserIdentity;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class SpnegoAuthenticator
/*     */   extends SSOAuthenticator
/*     */ {
/*     */   private SpnegoLoginService spnegoUserRealm;
/*     */   
/*     */   public SpnegoAuthenticator(HttpServletRequest req, HttpServletResponse resp, SpnegoLoginService spnegoUserRealm)
/*     */   {
/*  53 */     super(req, resp);
/*  54 */     this.spnegoUserRealm = spnegoUserRealm;
/*     */   }
/*     */   
/*     */   public String getAuthType()
/*     */   {
/*  59 */     return "Spnego";
/*     */   }
/*     */   
/*     */   public SSOAuthenticator.ZimbraPrincipal authenticate() throws ServiceException
/*     */   {
/*  64 */     Request request = (this.req instanceof Request) ? (Request)this.req : null;
/*     */     
/*  66 */     if (request == null) {
/*  67 */       throw ServiceException.FAILURE("not supported", null);
/*     */     }
/*  69 */     return getPrincipal(request);
/*     */   }
/*     */   
/*     */   private SSOAuthenticator.ZimbraPrincipal getPrincipal(Request request) throws ServiceException {
/*  73 */     SSOAuthenticator.ZimbraPrincipal principal = null;
/*     */     try
/*     */     {
/*  76 */       principal = authenticate(this.spnegoUserRealm, request, this.resp);
/*     */ 
/*     */     }
/*     */     catch (IOException e)
/*     */     {
/*     */ 
/*  82 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED("spnego authenticate failed", e);
/*     */     }
/*     */     
/*  85 */     if (principal == null) {
/*  86 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED("spnego authenticate failed", (Throwable)null);
/*     */     }
/*     */     
/*  89 */     return principal;
/*     */   }
/*     */   
/*     */   private Account getAccountByPrincipal(Principal principal)
/*     */     throws ServiceException
/*     */   {
/*  95 */     String krb5Name = principal.getName();
/*     */     
/*  97 */     Provisioning prov = Provisioning.getInstance();
/*  98 */     Account acct = prov.get(Key.AccountBy.krb5Principal, krb5Name);
/*     */     
/* 100 */     if (acct == null) {
/* 101 */       Domain domain = Krb5Principal.getDomainByKrb5Principal(krb5Name);
/* 102 */       if (domain != null) {
/* 103 */         acct = prov.autoProvAccountLazy(domain, krb5Name, null, ZAttrProvisioning.AutoProvAuthMech.SPNEGO);
/*     */       }
/*     */     }
/* 106 */     return acct;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private SSOAuthenticator.ZimbraPrincipal authenticate(LoginService realm, Request request, HttpServletResponse response)
/*     */     throws ServiceException, IOException
/*     */   {
/* 117 */     Principal user = null;
/* 118 */     String header = request.getHeader(HttpHeader.AUTHORIZATION.toString());
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 123 */     if (header == null) {
/* 124 */       sendChallenge(realm, request, response);
/* 125 */       throw SSOAuthenticator.SSOAuthenticatorServiceException.SENT_CHALLENGE();
/*     */     }
/* 127 */     if ((header != null) && (header.startsWith(HttpHeader.NEGOTIATE.toString())))
/*     */     {
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 133 */       String token = header.substring(10);
/*     */       
/* 135 */       UserIdentity identity = realm.login(null, token);
/* 136 */       if (identity == null) {
/* 137 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED("SpengoAuthenticator: unable to login", (Throwable)null);
/*     */       }
/* 139 */       user = identity.getUserPrincipal();
/*     */       
/* 141 */       if (user != null) {
/* 142 */         ZimbraLog.account.debug("SpengoAuthenticator: obtained principal: " + user.getName());
/*     */         
/* 144 */         Account acct = getAccountByPrincipal(user);
/* 145 */         SSOAuthenticator.ZimbraPrincipal zimbraPrincipal = new SSOAuthenticator.ZimbraPrincipal(user.getName(), acct);
/* 146 */         String clientName = ((SpnegoUserPrincipal)user).getName();
/* 147 */         String role = clientName.substring(clientName.indexOf('@') + 1);
/* 148 */         SpnegoUserIdentity spnegoUserIdentity = new SpnegoUserIdentity(identity.getSubject(), zimbraPrincipal, Arrays.asList(new String[] { role }));
/* 149 */         Authentication authentication = new UserAuthentication(getAuthType(), spnegoUserIdentity);
/* 150 */         request.setAuthentication(authentication);
/* 151 */         response.addHeader(HttpHeader.WWW_AUTHENTICATE.toString(), HttpHeader.NEGOTIATE.toString() + " " + ((SpnegoUserPrincipal)user).getToken());
/*     */         
/* 153 */         return zimbraPrincipal;
/*     */       }
/*     */       
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 160 */       ZimbraLog.account.debug("SpengoAuthenticator: no user found, authentication failed");
/* 161 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED("SpengoAuthenticator: no user found, authentication failed", (Throwable)null);
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 167 */     throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED("SpengoAuthenticator: authentication failed, unknown header (browser is likely misconfigured for SPNEGO)", (Throwable)null);
/*     */   }
/*     */   
/*     */   public void sendChallenge(LoginService realm, Request request, HttpServletResponse response)
/*     */     throws IOException
/*     */   {
/* 173 */     ZimbraLog.account.debug("SpengoAuthenticator: sending challenge");
/* 174 */     response.setHeader(HttpHeader.WWW_AUTHENTICATE.toString(), HttpHeader.NEGOTIATE.toString());
/* 175 */     response.sendError(401);
/*     */   }
/*     */   
/*     */   private static class MockSpnegoUser implements Principal
/*     */   {
/*     */     String name;
/*     */     String token;
/*     */     
/*     */     private static SSOAuthenticator.ZimbraPrincipal getMockPrincipal() throws IOException {
/* 184 */       Principal principal = new MockSpnegoUser("spnego@SPNEGO.LOCAL", "blah");
/* 185 */       SSOAuthenticator.ZimbraPrincipal zimbraPrincipal = null;
/*     */       try {
/* 187 */         zimbraPrincipal = new SSOAuthenticator.ZimbraPrincipal(principal.getName(), GuestAccount.ANONYMOUS_ACCT);
/*     */       }
/*     */       catch (ServiceException e) {}
/* 190 */       return zimbraPrincipal;
/*     */     }
/*     */     
/*     */     MockSpnegoUser(String name, String token) {
/* 194 */       this.name = name;
/* 195 */       this.token = token;
/*     */     }
/*     */     
/*     */     public String getName()
/*     */     {
/* 200 */       return this.name;
/*     */     }
/*     */     
/*     */     public String getToken() {
/* 204 */       return this.token;
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/service/authenticator/SpnegoAuthenticator.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */